﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Threading.Tasks;
using Cloud.Boss.Models;
using Cloud.Core.Cache;
using Cloud.Core.Data;
using Cloud.Entity;
using Cloud.Framework.Filter;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyModel;
using Cloud.Framework.Ioc;
using Cloud.Core.Service;
using Cloud.UnitOfWork;
using Cloud.Core.Http;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;


namespace Cloud.Boss
{

    /*
     * 参考官网：https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/startup?view=aspnetcore-3.1
     Startup类必须包含Configure方法，并可以选择包含ConfigureServices方法，这两个方法在应用程序启动时调用。
    该类还可以包含这些方法的特定于环境的版本。 ConfigureServices（如果存在）在Configure之前调用。

    Configure方法主要是配置ASP.NET Core的中间件，相当于我们在ASP.NET中所说的管道，ConfigureServices主要是配置依赖注入
     */
    public class Startup
    {
        public Startup(IConfiguration configuration, IWebHostEnvironment env)
        {
            myEnv = env;
            Configuration = configuration;

        }
        private IWebHostEnvironment myEnv;

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //配置EF的连接字符串
            //services.AddDbContext<EfDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            var con = Configuration.GetConnectionString("DefaultConnection");

           // services.AddDbContext<EfDbContext>(options => options.UseMySql(con, new MySqlServerVersion(new Version(5, 7))));

            services.AddDbContextPool<EfDbContext>(options => options.UseMySql(con, new MySqlServerVersion(new Version(5, 7))),poolSize:64);

            services.AddControllersWithViews();


            //使用UnitOfWork代替Repository，在UnitOfWork中直接new Repository，不在这里依赖注入了
            //services.AddScoped(typeof(IRepository<>), typeof(EfRespository<>));
            services.AddScoped(typeof(IUnitOfWork), typeof(EfUnitOfWork));

            //内存缓存单例模式
            services.AddSingleton<ICacheManager, CacheManager>();

            //https://github.com/2881099/csredis
            //添加redis连接
            var csredis = new CSRedis.CSRedisClient("ip:6379,password=密码,defaultDatabase=0,poolsize=100");
            
            //初始化 RedisHelper
            RedisHelper.Initialization(csredis);

            //动态注册IOC
            services.BatchAddScoped("Cloud.Service");


            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            LogServiceHelper.Intance.Start(myEnv.WebRootPath + "/log/", 1024 * 64);
            LogServiceHelper.Intance.Write(new LogModel() { CreatedTime = DateTime.Now, Dir = "application", Msg = "系统重启", Operator = "" });
            services.AddMemoryCache();//启用内存缓存
            services.Configure<ProjectSetting>(Configuration.GetSection("ProjectSetting"));

            //web服务器配置
            //直接在program中配置
           // services.Configure<KestrelServerOptions>(Configuration.GetSection("Kestrel"));
            services.AddMvc(options =>
            {
                options.Filters.Add<GlobalExceptionFilter>();//异常过滤器
                options.Filters.Add(typeof(GlobalAuthorizeFilter));//权限过滤器

            });

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {



            if (env.IsDevelopment())//开发环境，使用异常页面显示异常
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {

                // app.UseExceptionHandler("/Home/Error");
                app.UseExceptionHandler(builder => builder.Run(async context => await ErrorEvent(context)));
            }

            //HTTPS 重定向中间件 (UseHttpsRedirection) 将 HTTP 请求重定向到 HTTPS。
            //app.UseHttpsRedirection();

            //将wwwroot下的静态文件映射到根目录，ps:~/images/MyImage.jpg实际指向wwwroot/images/MyImage.jpg
            //访问时不需要带上wwwroot目录
            app.UseStaticFiles();


            //设置路由
            app.UseRouting();

            //  app.UseAuthorization();

            app.UseEndpoints(endpoints =>
             {
                 endpoints.MapControllerRoute(
                       name: "login",
                       pattern: "{controller=Account}/{action=Login}/{id?}");

                 endpoints.MapControllerRoute(
                                 name: "default",
                                 pattern: "{controller=Home}/{action=Index}/{id?}");
             });


        }
        public Task ErrorEvent(Microsoft.AspNetCore.Http.HttpContext context)
        {
            var feature = context.Features.Get<IExceptionHandlerFeature>();
            var error = feature?.Error;
            var path = ((Microsoft.AspNetCore.Diagnostics.ExceptionHandlerFeature)feature).Path;
            Core.Service.LogServiceHelper.Intance.Write(new LogModel() { CreatedTime = DateTime.Now, Dir = "exception", Msg = path + "，错误信息:" + error.Message, Operator = "" });
            throw error;
        }
    }
}
